package com.eastfair.imaster.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.eastfair.annotation.base.LanguageTypeEnum;
import com.eastfair.auth.api.AuthServiceFeign;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.auth.dto.OrganizationDTO;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.entity.Organization;
import com.eastfair.auth.enumeration.OrganizationOrgTypeEnum;
import com.eastfair.auth.enumeration.ResourceOrganizationResourceTypeEnum;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.code.ExceptionCode;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.imaster.dao.CompanyMapper;
import com.eastfair.imaster.dto.CompanyDTO;
import com.eastfair.imaster.dto.EmployeeDTO;
import com.eastfair.imaster.entity.Company;
import com.eastfair.imaster.entity.CompanyError;
import com.eastfair.imaster.service.*;
import com.eastfair.imaster.vo.CompanyVo;
import com.eastfair.imaster.vo.EmployeeVo;
import com.eastfair.projectcore.api.ProjectCoreServiceFeign;
import com.eastfair.core.snowflake.DefaultUidGenerator;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.eastfair.core.base.R.SUCCESS_CODE;

/**
 * <p>
 * 业务实现类
 * 公司表
 * </p>
 *
 * @author ligang
 * @date 2021-08-19
 */
@Slf4j
@Service
@Transactional
@DS("#thread.tenant")
public class CompanyServiceImpl extends SuperServiceImpl<CompanyMapper, Company> implements CompanyService {

    @Autowired
    ProjectCoreServiceFeign projectCoreServiceFeign;

    @Autowired
    EmployeeService employeeService;

    @Autowired
    AuthServiceFeign authServiceFeign;

    @Autowired
    CompanyErrorService companyErrorService;

    @Autowired
    CheckEmployeeService checkEmployeeService;
    @Autowired
    UserAccountServiceFeign userAccountServiceFeign;

    @Autowired
    private TccService tccService;

    /**************sharding 分库分表操作 *****************/
    @Override
    public boolean updateByIdOfShard(Company entity) {
        UpdateWrapper<Company> updateWrapper = new UpdateWrapper<>();
        //可将指定字段更新为null
        updateWrapper.lambda().eq(Company::getProjectId, entity.getProjectId()).eq(Company::getId, entity.getId());
        entity.setProjectId(null);
        //删除缓存
        //delCache(entity);
        return SqlHelper.retBool(this.getBaseMapper().update(entity, updateWrapper));
    }

    @Override
    protected R<Boolean> handlerSave(Company model) {
        //项目id
        model.setProjectId(ContextUtil.getProjectId());
        //雪花ID
        model.setId(DefaultUidGenerator.getUidOfProjectId(model.getProjectId()));
        return R.successDef();
    }

    @Override
    @Transactional
    public CompanyVo saveCompany(CompanyDTO companyDTO, Long adminUserId) {
        Company company = BeanUtil.toBean(companyDTO, Company.class);
        //创建公司
        save(company);
        if (adminUserId == null) {
            //创建公司管理员用户
            UserAccountDto userAccountDto = new UserAccountDto();
            userAccountDto.setProjectId(ContextUtil.getProjectId());
            userAccountDto.setName(companyDTO.getAdminName());
            userAccountDto.setMobile(companyDTO.getAdminMobile());
            userAccountDto.setEmail(companyDTO.getAdminEmail());
            R<UserAccountVo> accountVoR = userAccountServiceFeign.addAdminUser(userAccountDto);
            if (accountVoR.getCode() == SUCCESS_CODE) {
                adminUserId = accountVoR.getData().getId();
            }
        }
        //创建组织角色
        OrganizationDTO organizationDTO = new OrganizationDTO();
        //资源id
        organizationDTO.setResourceId(company.getId());
        //节点管理员
        organizationDTO.setUserIds(Arrays.asList(adminUserId));
        //资源名称
        organizationDTO.setName(company.getName());
        organizationDTO.setProjectId(ContextUtil.getProjectId());
        //指定组织id
        organizationDTO.setOrgIds(companyDTO.getOrgIds());
        //添加公司到组织
        R<Organization> organizationR = authServiceFeign.addCompany(organizationDTO);
        if (organizationR.getCode() == SUCCESS_CODE) {
//            //将角色注入到公司组织
//            OrganizationRoleDto orgRoleDto = new OrganizationRoleDto();
//            orgRoleDto.setRoleIds(roleIds);
//            orgRoleDto.setOrganizationId(organizationR.getData().getId());
//            orgRoleDto.setConduction(false);
//            authServiceFeign.addOrgRole(orgRoleDto);
        }
        //组织角色：添加为公司员工
        EmployeeDTO employeeDTO = new EmployeeDTO();
        employeeDTO.setCompanyId(company.getId());
        employeeDTO.setUserAccountId(adminUserId);
        employeeDTO.setIsAdmin(1);
        employeeService.addUserIdOfCompany(employeeDTO);
        CompanyVo companyVo = new CompanyVo();
        BeanUtil.copyProperties(company, companyVo);
        return companyVo;
    }

    @Override
    public Company companyIsExist(CompanyDTO companyDTO) {
        // TODO: 2021/8/28 查询公司是否重复规则
        Company company = BeanUtil.toBean(companyDTO, Company.class);
        List<Company> companyList = list(company, null);
        if (companyList != null && !companyList.isEmpty()) {
            return companyList.get(0);
        }
        return null;
    }

    @Override
    public R<CompanyVo> checkCompany(Long companyId, Boolean isCheck) {
        List<Company> companyList = list(null, Arrays.asList(companyId));
        if (companyList != null && !companyList.isEmpty()) {
            Company company = companyList.get(0);
            //审核是否通过
            if (isCheck) {
                company.setIsAuthentication(BusinessConstant.YES);
            } else {
                company.setIsAuthentication(BusinessConstant.NO);
            }
            //更新
            updateByIdOfShard(company);
            return R.successDef(BeanUtil.copyProperties(company, CompanyVo.class));
        }
        return R.fail(ExceptionCode.COMPANY_CHECK_FAIL);
    }

    @Override
    public List<Company> list(Company company, List<Long> ids) {
        //查询
        QueryWrapper<Company> queryWrapper = new QueryWrapper<>();
        if (company != null) {
            if (company.getId() != null) {
                queryWrapper.lambda().eq(Company::getId, company.getId());
            }
            if (StringUtils.isNotBlank(company.getName())) {
                queryWrapper.lambda().eq(Company::getName, company.getName());
            }
            if (StringUtils.isNotBlank(company.getIdentificationNumber())) {
                queryWrapper.lambda().eq(Company::getIdentificationNumber, company.getIdentificationNumber());
            }
        }
        if (ContextUtil.getProjectId() != null) {
            queryWrapper.lambda().eq(Company::getProjectId, ContextUtil.getProjectId());
        }
        if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(Company::getId, ids);
        }
        queryWrapper.lambda().eq(Company::getIsDeleted, BusinessConstant.DELETE_NO);
        List<Company> companyList = list(queryWrapper);
        return companyList;
    }

    @Override
    public List<CompanyVo> queryCompany(CompanyDTO companyDTO) {
        Company company = BeanUtil.copyProperties(companyDTO, Company.class);
        List<Company> companyList = list(company, null);
        if (companyList != null && !companyList.isEmpty()) {
            List<CompanyVo> companyVoList = ConvertUtil.convertList(companyList, CompanyVo.class);
            for (CompanyVo companyVo : companyVoList) {
                //公司下的员工
                EmployeeDTO employeeDTO = new EmployeeDTO();
                employeeDTO.setCompanyId(companyVo.getId());
                companyVo.setEmployeeVoList(employeeService.queryEmployeeOfCompany(employeeDTO));
            }
            return companyVoList;
        }
        return null;
    }

    /**
     * 业务功能:添加公司
     * 1当公司未认证并重复，加入到冲突表
     * 2当公司不存在，则新增公司和管理员
     * 3当公司认证并重复，则用户加入到公司
     *
     * @return
     */
    @Override
//    @Transactional
//    @GlobalTransactional(name = "company", rollbackFor = Exception.class)
//    @ShardingTransactionType(TransactionType.BASE)
    public R<CompanyVo> executeCreateCompany(CompanyDTO companyDTO, Long adminUserId) {
        String xid = RootContext.getXID();
        log.info("executeCreateCompany 事务id is {}", xid);
        if (companyDTO.getIsAuthentication() == null) {
            companyDTO.setIsAuthentication(BusinessConstant.NO);
        }
        //公司是否存在
        Company company = companyIsExist(companyDTO);
        if (company != null) {
            //存在
            if (BusinessConstant.YES == company.getIsAuthentication()) {
                //已认证，加入公司成为员工，待审核
                checkEmployeeService.addUserIdOfCompany(company.getId(), adminUserId, true, 0);
            } else {
                //未认证，加入公司冲突表
                CompanyError companyError = new CompanyError();
                //记录冲突id
                companyError.setConflictId(company.getId());
                // TODO: 2021/8/31 记录异常信息
                companyErrorService.save(companyError);
                return R.fail(ExceptionCode.COMPANY_ERROR);
            }
        } else {
            //新增公司，并添加管理员
            CompanyVo companyVo = saveCompany(companyDTO, adminUserId);
            return R.success(companyVo);

        }
        return R.fail("操作失败");
    }

    @Override
    public R<CompanyVo> executeUpdCompany(CompanyDTO companyDTO) {
        Company company = BeanUtil.toBean(companyDTO, getEntityClass());
        //更新
        updateById(company);
        //替换projectId 全局id
        ContextUtil.setProjectId(company.getProjectId());
        //更新组织
        OrganizationDTO organizationDTO = new OrganizationDTO();
        organizationDTO.setName(company.getName());
        organizationDTO.setResourceId(company.getId());
        organizationDTO.setResourceType(ResourceOrganizationResourceTypeEnum.COMPANY);
        organizationDTO.setProjectId(company.getProjectId());
        organizationDTO.setOrgIds(companyDTO.getOrgIds());
        R<Organization> organizationR = authServiceFeign.updCompany(organizationDTO);
//        if (organizationR.getCode() == SUCCESS_CODE) {
//            Long orgId = organizationR.getData().getId();
//            //重新将角色注入到项目组织
//            OrganizationRoleDto orgRoleDto = new OrganizationRoleDto();
//            orgRoleDto.setRoleIds(companyDTO.getRoleIds());
//            orgRoleDto.setOrganizationId(orgId);
//            orgRoleDto.setConduction(false);
//            authServiceFeign.updOrgRole(orgRoleDto);
//        }
        CompanyVo companyVo = new CompanyVo();
        BeanUtil.copyProperties(company, companyVo);
        return R.success(companyVo);
    }

    @Override
    public CompanyVo findById(Long id) {
        Company company = getById(id);
        CompanyVo companyVo = doToVo(company);
        return companyVo;
    }

    @Override
    public CompanyVo findAllUserById(Long id) {
        CompanyVo companyVo = findById(id);
        if(companyVo!=null){
            //公司下的员工
            EmployeeDTO employeeDTO = new EmployeeDTO();
            employeeDTO.setCompanyId(companyVo.getId());
            companyVo.setEmployeeVoList(employeeService.queryEmployeeOfCompany(employeeDTO));
        }
        return companyVo;
    }

    @Override
    public CompanyVo getAndRoleById(Long id) {
        Company company = getById(id);
        if (company != null) {
            CompanyVo companyVo = doToVo(company);
            //查询角色
            //替换projectId 全局id
//            ContextUtil.setProjectId(companyVo.getProjectId());
            //查询项目下的类型节点信息
            OrganizationDTO organizationDTO = new OrganizationDTO();
            organizationDTO.setParentId(companyVo.getProjectId());
            organizationDTO.setOrgType(OrganizationOrgTypeEnum.P_COMPANY_CLASSIFY);
            R<Organization> organizationR = authServiceFeign.queryOrgOfType(organizationDTO);
            if (organizationR.getCode() == SUCCESS_CODE) {
                Organization organization = organizationR.getData();
                R<List<Long>> r = authServiceFeign.queryOrgOfResourceId(companyVo.getId(), organization.getId());
                if (r.getCode() == SUCCESS_CODE) {
                    List<Long> orgIds = r.getData();
                    companyVo.setOrgIds(orgIds);
                }
            }
            //加载管理员信息
            EmployeeDTO employeeDTO = new EmployeeDTO();
            employeeDTO.setCompanyId(companyVo.getId());
            List<EmployeeVo> employeeVoList = employeeService.queryEmployeeOfCompany(employeeDTO);
            if (employeeVoList != null && !employeeVoList.isEmpty()) {
                UserAccountDto userAccountDto = new UserAccountDto();
                employeeVoList = employeeVoList.stream().filter((filed) -> filed.getIsAdmin() == BusinessConstant.YES).collect(Collectors.toList());
                userAccountDto.setUserIds(employeeVoList.stream().map(EmployeeVo::getUserAccountId).collect(Collectors.toList()));
                R<List<UserAccountVo>> listR = userAccountServiceFeign.querySimpleByIds(userAccountDto);
                if (SUCCESS_CODE == listR.getCode()) {
                    List<UserAccountVo> userAccountVoList = listR.getData();
                    if (userAccountVoList != null && !userAccountVoList.isEmpty()) {
                        companyVo.setAdminName(userAccountVoList.get(0).getName());
                        companyVo.setAdminMobile(userAccountVoList.get(0).getMobile());
                        companyVo.setAdminEmail(userAccountVoList.get(0).getEmail());
                    }
                }
            }
            return companyVo;
        }
        return null;
    }

    @Override
    public R<Page<CompanyVo>> queryPage(PageParams<CompanyDTO> params) {
        QueryWrapper<Company> queryWrapper = new QueryWrapper<>();
        CompanyDTO companyDTO = params.getModel();
        queryWrapper.lambda().eq(Company::getProjectId, ContextUtil.getProjectId())
                .eq(Company::getIsDeleted, BusinessConstant.DELETE_NO);
        if (companyDTO != null) {
            if (StringUtils.isNotBlank(companyDTO.getName())) {
                queryWrapper.lambda().like(Company::getName, companyDTO.getName());
            }
            if (companyDTO.getOrgIds() != null && !companyDTO.getOrgIds().isEmpty()) {
                //查询组织关联的角色
                R<List<Long>> r = authServiceFeign.queryResourceId(companyDTO.getOrgIds());
                if (r.getCode() == SUCCESS_CODE) {
                    List<Long> resourceIds = r.getData();
                    queryWrapper.lambda().in(Company::getId, resourceIds);
                }
            }
        }
        Page<Company> page = page(params.buildPage(), queryWrapper);
        Page<CompanyVo> voPage = ConvertUtil.convertPage(page, CompanyVo.class);
        List<CompanyVo> voList = voPage.getRecords();
        if (voList.isEmpty()) {
            return R.success(voPage);
        }
        //加载管理员信息
        for (CompanyVo companyVo : voList) {

            EmployeeDTO employeeDTO = new EmployeeDTO();
            employeeDTO.setCompanyId(companyVo.getId());
            List<EmployeeVo> employeeVoList = employeeService.queryEmployeeOfCompany(employeeDTO);
            if (employeeVoList != null && !employeeVoList.isEmpty()) {
                UserAccountDto userAccountDto = new UserAccountDto();
                employeeVoList = employeeVoList.stream().filter((filed) -> filed.getIsAdmin() == BusinessConstant.YES).collect(Collectors.toList());
                userAccountDto.setUserIds(employeeVoList.stream().map(EmployeeVo::getUserAccountId).collect(Collectors.toList()));
                R<List<UserAccountVo>> listR = userAccountServiceFeign.querySimpleByIds(userAccountDto);
                if (SUCCESS_CODE == listR.getCode()) {
                    List<UserAccountVo> userAccountVoList = listR.getData();
                    if (userAccountVoList != null && !userAccountVoList.isEmpty()) {
                        companyVo.setAdminName(userAccountVoList.get(0).getName());
                        companyVo.setAdminMobile(userAccountVoList.get(0).getMobile());
                        companyVo.setAdminEmail(userAccountVoList.get(0).getEmail());
                    }
                }
            }
        }
        assembleCompanyVoList(voList);
        voPage.setRecords(voList);
        return R.success(voPage);
    }

    @Override
    public void assembleCompanyVoList(List<CompanyVo> companyVoList) {
        //查询公司所在的组织
        OrganizationDTO organizationDTO = new OrganizationDTO();
        organizationDTO.setProjectId(ContextUtil.getProjectId());
        //项目下的公司分组节点
        organizationDTO.setOrgType(OrganizationOrgTypeEnum.P_COMPANY_CLASSIFY);
        R<Organization> r = authServiceFeign.queryOrgOfType(organizationDTO);
        if (r.getCode() == SUCCESS_CODE) {
            //组织信息
            Organization organization = r.getData();
            R<Map<Long, List<Organization>>> mapR = authServiceFeign.queryOrgOfResource(companyVoList.stream().map(CompanyVo::getId).collect(Collectors.toList()), Arrays.asList(organization.getId()));
            if (mapR.getCode() == SUCCESS_CODE) {
                Map<Long, List<Organization>> map = mapR.getData();
                for (CompanyVo companyVo : companyVoList) {
                    List<Organization> organizationList = map.get(companyVo.getId());
                    if (organizationList != null && !organizationList.isEmpty()) {
                        companyVo.setOrgIds(organizationList.stream().map(Organization::getId).collect(Collectors.toList()));
                        companyVo.setOrgNames(organizationList.stream().map(Organization::getName).collect(Collectors.toList()));
                    }
                }
            }
        }

    }

    @Override
    public Boolean delCompany(List<Long> companyIds) {
        for (Long companyId : companyIds) {
            //删除公司
            Company company = getById(companyId);
            if (company != null) {
                company.setIsDeleted(BusinessConstant.DELETE_YES);
                updateById(company);
                //删除公司员工
                employeeService.breaklUserIdOfCompany(company.getId());
            }
        }

        return null;
    }


    public CompanyVo doToVo(Company company) {
        CompanyVo companyVo = new CompanyVo();
        BeanUtils.copyProperties(company, companyVo);
        companyVo.setId(company.getId());

        return companyVo;
    }

    public List<CompanyVo> doToVos(List<Company> companyList) {
        if (companyList == null || companyList.isEmpty()) {
            return null;
        }
        List<CompanyVo> result = new ArrayList<>();
        for (Company company : companyList) {
            result.add(doToVo(company));
        }
        return result;
    }


    @Override
    @GlobalTransactional
//    @GlobalTransactional(name = "executeTcc" , rollbackFor = Exception.class)
    public R executeTcc(Long id) {
        String xid = RootContext.getXID();
        System.out.println("executeTcc prepare, xid:" + xid + ", id:" + id);
        tccService.executeTest(null, id, "test");
        int i = 1;
        if (i == 1) {
            throw new RuntimeException("公司不存在");
        }
        return null;
    }

}
